package com.example.xunai.service.ai.impl;

import com.example.xunai.config.AiModelConfig;
import com.example.xunai.entity.ConversationMessage;
import com.example.xunai.service.ai.SyncChatService;
import com.example.xunai.service.conversation.ConversationMessageService;
import com.example.xunai.service.user.TokenUsageService;
import com.example.xunai.service.ai.strategy.AiModelFactory;
import com.example.xunai.service.ai.strategy.AiModelStrategy;
import com.example.xunai.dto.request.ai.ChatRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor
public class SyncChatServiceImpl implements SyncChatService {

    private final AiModelFactory aiModelFactory;
    private final AiModelConfig aiModelConfig;
    private final ConversationMessageService conversationMessageService;
    private final TokenUsageService tokenUsageService;

    @Override
    public String getAiResponse(ChatRequest request) {
        log.info("开始同步聊天，请求: {}", request.toLogString());

        if (!request.isValid()) {
            throw new IllegalArgumentException("聊天请求参数无效: " + request);
        }

        return internalGetAiResponse(
                request.getUserMessage(),
                request.getSessionId(),
                request.getConversationId(),
                request.getModelType(),
                request.getUserId()
        );
    }

    /**
     * 内部同步聊天实现
     */
    private String internalGetAiResponse(String userMessage, String sessionId, Long conversationId,
                                         String modelType, Long userId) {
        try {
            // 保存用户消息
            ConversationMessage userMsg = saveMessageToDatabase(conversationId, "user", userMessage, null);

            // 构建对话上下文
            List<Map<String, String>> conversationContext = buildDatabaseConversationContext(conversationId);

            // 获取模型配置和策略
            AiModelConfig.ModelConfig config = aiModelConfig.getModels().get(modelType);
            AiModelStrategy strategy = aiModelFactory.getStrategy(modelType);

            if (!strategy.validateConfig(config)) {
                throw new RuntimeException("模型配置无效: " + modelType);
            }

            // 调用模型
            String aiResponse = strategy.chatSync(userMessage, conversationContext, config);

            if (aiResponse != null) {
                // 保存AI回复
                ConversationMessage aiMessage = saveMessageToDatabase(conversationId, "assistant", aiResponse, userMsg.getTurn() + 1);

                // 记录token使用
                int inputTokens = estimateTokens(userMessage) + estimateContextTokens(conversationContext);
                int outputTokens = estimateTokens(aiResponse);
                tokenUsageService.recordTokenUsage(userId, conversationId, aiMessage.getId(), modelType, inputTokens, outputTokens);

                return aiResponse;
            }

            return "AI响应为空";

        } catch (Exception e) {
            log.error("同步聊天失败", e);
            return "请求出错: " + e.getMessage();
        }
    }

    // ==================== 私有辅助方法 ====================

    /**
     * 保存消息到数据库
     */
    private ConversationMessage saveMessageToDatabase(Long conversationId, String role, String content, Integer turn) {
        if (conversationId == null) {
            log.error("无法保存消息，conversationId 为 null");
            return null;
        }

        try {
            if (turn == null) {
                Integer lastTurn = conversationMessageService.getLastTurnByConversationId(conversationId);
                turn = lastTurn != null ? lastTurn + 1 : 1;
            }

            ConversationMessage message = new ConversationMessage();
            message.setConversationId(conversationId);
            message.setTurn(turn);
            message.setRole(ConversationMessage.MessageRole.valueOf(role));
            message.setContent(content);
            message.setCreateTime(java.time.LocalDateTime.now());

            ConversationMessage savedMessage = conversationMessageService.saveMessage(message);
            log.debug("成功保存消息，对话ID: {}, 角色: {}, 内容长度: {}", conversationId, role, content.length());
            return savedMessage;
        } catch (Exception e) {
            log.error("保存消息失败，对话ID: {}, 角色: {}, 错误: {}", conversationId, role, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 估算文本的token数量
     */
    private int estimateTokens(String text) {
        if (text == null || text.isEmpty()) return 0;

        int chineseChars = 0;
        int englishChars = 0;

        for (char c : text.toCharArray()) {
            if (Character.toString(c).matches("[\\u4e00-\\u9fa5]")) {
                chineseChars++;
            } else if (Character.isLetterOrDigit(c) || Character.isWhitespace(c)) {
                englishChars++;
            } else {
                englishChars++;
            }
        }

        int estimatedTokens = (int) Math.ceil(chineseChars / 1.5) + (int) Math.ceil(englishChars / 3.0);
        return Math.max(1, estimatedTokens);
    }

    /**
     * 估算对话上下文的token数量
     */
    private int estimateContextTokens(List<Map<String, String>> conversationContext) {
        if (conversationContext == null || conversationContext.isEmpty()) {
            return 0;
        }

        int totalTokens = 0;
        for (Map<String, String> message : conversationContext) {
            String role = message.get("role");
            String content = message.get("content");

            if (role != null) {
                totalTokens += estimateTokens(role);
            }
            if (content != null) {
                totalTokens += estimateTokens(content);
            }
        }

        return totalTokens;
    }

    private List<Map<String, String>> buildDatabaseConversationContext(Long conversationId) {
        if (conversationId == null) return new java.util.ArrayList<>();

        try {
            List<ConversationMessage> messages = conversationMessageService.getMessagesByConversationId(conversationId);
            List<Map<String, String>> context = new java.util.ArrayList<>();

            for (ConversationMessage message : messages) {
                Map<String, String> msgMap = new java.util.HashMap<>();
                msgMap.put("role", message.getRole().name());
                msgMap.put("content", message.getContent());
                context.add(msgMap);
            }

            return context;
        } catch (Exception e) {
            log.error("构建对话上下文失败", e);
            return new java.util.ArrayList<>();
        }
    }
}